﻿// Fill out your copyright notice in the Description page of Project Settings.

#include "GameLiftModel.h"


FOneNodeBase::FOneNodeBase()
	: pointX(0), pointY(0), pointZ(0),index(0)
	, liftNow(0),liftBuffer(0), nearNodeNum(0), nearNodePtrList(nullptr)
{

}
FOneNodeBase::~FOneNodeBase()
{
	if (nearNodePtrList) {
		delete[] nearNodePtrList;
	}
	liftNow = liftBuffer = 0;
}


void FOneNodeBase::Init(uint16 x, uint16 y, uint16 z, int i, uint16 n, FOneNodeBase** nerbList)
{
	pointX = x;
	pointY = y;
	pointZ = z;
	index = i;
	nearNodeNum = n;
	nearNodePtrList = new FOneNodeBase*[nearNodeNum];

	for (int s = 0; s < nearNodeNum; s++)
	{
		nearNodePtrList[s] = nerbList[s];
	}

	//memcpy(nerbList, nearNodePtrList, nearNodeNum * sizeof(FOneNodeBase*));
}

void FOneNodeBase::SetLift(uint8 l)
{
	liftNow = liftBuffer = l;
}
uint8 FOneNodeBase::GetLift()const
{
	return liftNow;
}

uint8 FOneNodeBase::GetLiftBuffer()const
{
	return liftBuffer;
}



inline void FOneNodeBase::SetNowLift(uint8 lift)
{
	liftNow = lift;
}

int FOneNodeBase::GetIndex()const
{
	return index;
}

FIntVector FOneNodeBase::GetPoint()const
{
	return FIntVector(pointX, pointY, pointZ);
}

#pragma optimize("",off)

/**更新该结点状态*/
void FOneNodeBase::SaveBuffer() 
{
	liftBuffer = liftNow;
}



int FOneNode2D::UpDataLift()
{
	int templ = 0;
	for (int i = 0; i < nearNodeNum; i++)
	{
		templ = templ + nearNodePtrList[i]->GetLiftBuffer();

	}

	if (templ == 3)
	{
		SetNowLift(1);	
	}
	else
	{
		if (templ == 2)
		{

		}
		else
		{
			SetNowLift(0);
		}
	}

	return GetLift();
}



uint8 FOneNode3D::minKeep = 5;
uint8 FOneNode3D::maxKeep = 8;
uint8 FOneNode3D::maxNear = 12;


int FOneNode3D::UpDataLift()
{
	int templ = 0;
	for (int i = 0; i < nearNodeNum; i++)
	{
		templ = templ + nearNodePtrList[i]->GetLiftBuffer();

	}




	if (templ >= maxKeep && templ <= maxNear)
	{
		SetNowLift(1);
	}
	else
	{
		if (templ >= minKeep && templ < maxKeep)
		{

		}
		else
		{
			SetNowLift(0);
		}
	}


	//if (templ >= 12&& templ <= 18)
	//{
	//	SetNowLift(1);
	//}
	//else 
	//{
	//	if (templ > 8 && templ < 12) 
	//	{

	//	}
	//	else 
	//	{
	//		SetNowLift(0);
	//	}
	//}

	//int a = 8, b = 11, c = 12, d = 18;
	//if (templ <= a)
	//{
	//	SetNowLift(0);
	//}
	//if (templ > a&& templ<= d)
	//{
	//	if (templ > b&& templ <= c)
	//	{
	//		SetNowLift(1);
	//	}
	//}
	//if (templ >= d)
	//{
	//	SetNowLift(0);
	//}


	return 0;
}



FLiftWorld::FLiftWorld() :
	sizeX(0), sizeY(0), sizeZ(0)
	, numXY(0), allnum(0), allNode(nullptr), edgeLifeNode(nullptr)
	, liveTime(0)
{

}

FLiftWorld::~FLiftWorld() 
{
	if (allNode) 
	{
		delete[] allNode;
	}
	if (edgeLifeNode) 
	{
		delete edgeLifeNode;
	}
}


bool FLiftWorld::IsValid() const
{
	return allnum >= 27 && allNode != nullptr;
}

FIntVector  FLiftWorld::GetWorldSize()const
{
	return FIntVector(sizeX, sizeY, sizeZ);
}

uint32  FLiftWorld::GetAllNode()const
{
	return allnum;
}

uint32 FLiftWorld::GetLiveTime()const
{
	return liveTime;
}


/**获取指定位置的节点*/
inline const FOneNodeBase* FLiftWorld::GetNodeC(uint32 index)const
{
	if (index < allnum)
	{
		return &allNode[index];
	}
	return nullptr;
}


inline int FLiftWorld::GetIndex(uint16 x, uint16 y, uint16 z)const
{
	return z * numXY + y * sizeY + x;
}

void FLiftWorld::SetNodeLift(uint32 index, uint8 lift)
{
	FOneNodeBase* n = GetNode(index);
	if (n)
	{
		n->SetLift(lift);
	}
}

inline const FOneNodeBase* FLiftWorld::GetNodeC(int x, int y, int z)const
{

	x = (x + sizeX)%sizeX;
	y = (y + sizeX) % sizeY;
	z = (z + sizeX) % sizeZ;

	if (x < 0 || x >= sizeX)
	{
		return edgeLifeNode;
	}

	if (y < 0 || y >= sizeY)
	{
		return edgeLifeNode;
	}

	if (z < 0 || z >= sizeZ)
	{
		return edgeLifeNode;
	}


	return GetNodeC(GetIndex(x, y, z));

	//const FOneNodeBase* ss = nullptr;
	//ss = new FOneNodeBase();
	//ss->UpDataLift();//错误

	//FOneNodeBase* const css = nullptr;
	//css = new FOneNodeBase();//错误

}
/**获取指定位置的节点*/
FOneNodeBase* FLiftWorld::GetNode(uint32 index)
{
	if (index < allnum)
	{
		return &allNode[index];
	}
	return nullptr;
}

/**获取指定位置的节点*/
inline FOneNodeBase* FLiftWorld::GetNode(int x, int y, int z)
{
	x = (x + sizeX) % sizeX;
	y = (y + sizeX) % sizeY;
	z = (z + sizeX) % sizeZ;


	if (x < 0 || x >= sizeX)
	{
		return edgeLifeNode;
	}

	if (y < 0 || y >= sizeY)
	{
		return edgeLifeNode;
	}

	if (z < 0 || z >= sizeZ)
	{
		return edgeLifeNode;
	}

	int temp = GetIndex(x, y, z);
	return GetNode(temp);
}


//#include <vector>

void FLiftWorld::InitOne(int x, int y, int z, uint32 i)
{
	FOneNodeBase& node = allNode[GetIndex(x, y, z)];
	node.SetLift(0);

	int num = 0;
	if (sizeZ == 1)
	{
		FOneNodeBase** near = new FOneNodeBase*[8];

		near[num] = GetNode(x - 1, y - 1, z);
		num++;
		near[num] = GetNode(x, y - 1, z);
		num++;
		near[num] = GetNode(x + 1, y - 1, z);
		num++;

		near[num] = GetNode(x - 1, y, z);
		num++;
		near[num] = GetNode(x + 1, y, z);
		num++;

		near[num] = GetNode(x - 1, y + 1, z);
		num++;
		near[num] = GetNode(x, y + 1, z);
		num++;
		near[num] = GetNode(x + 1, y + 1, z);
		num++;



		node.Init(x, y, z, i, num, near);

		delete[] near;

		return;
	}
	else
	{
		FOneNodeBase** near = new FOneNodeBase*[26];
		//node.Init(x, y, z, i, num, nullptr);

		//int temp = sizeof(near);

		//memset(near,0, 26);

		near[num] = GetNode(x - 1, y - 1, z - 1);
		num++;

		near[num] = GetNode(x, y - 1, z - 1);
		num++;
		near[num] = GetNode(x + 1, y - 1, z - 1);
		num++;

		near[num] = GetNode(x - 1, y, z - 1);
		num++;
		near[num] = GetNode(x, y, z - 1);
		num++;
		near[num] = GetNode(x + 1, y, z - 1);
		num++;

		near[num] = GetNode(x - 1, y + 1, z - 1);
		num++;
		near[num] = GetNode(x, y + 1, z - 1);
		num++;
		near[num] = GetNode(x + 1, y + 1, z - 1);
		num++;
		//////////////////////////////////////////////////////////
		near[num] = GetNode(x - 1, y - 1, z);
		num++;
		near[num] = GetNode(x, y - 1, z);
		num++;
		near[num] = GetNode(x + 1, y - 1, z);
		num++;

		near[num] = GetNode(x - 1, y, z);
		num++;
		near[num] = GetNode(x + 1, y, z);
		num++;

		near[num] = GetNode(x - 1, y + 1, z);
		num++;
		near[num] = GetNode(x, y + 1, z);
		num++;
		near[num] = GetNode(x + 1, y + 1, z);
		num++;
		///////////////////////////////////////////////////////
		near[num] = GetNode(x - 1, y - 1, z + 1);
		num++;
		near[num] = GetNode(x, y - 1, z + 1);
		num++;
		near[num] = GetNode(x + 1, y - 1, z + 1);
		num++;

		near[num] = GetNode(x - 1, y, z + 1);
		num++;
		near[num] = GetNode(x, y, z + 1);
		num++;
		near[num] = GetNode(x + 1, y, z + 1);
		num++;

		near[num] = GetNode(x - 1, y + 1, z + 1);
		num++;
		near[num] = GetNode(x, y + 1, z + 1);
		num++;
		near[num] = GetNode(x + 1, y + 1, z + 1);
		num++;
		//////////////////////////////////////////////////////

		node.Init(x, y, z, i, num, near);

		delete[] near;

	}
}


bool FLiftWorld::InitWorld(uint16 x, uint16 y, uint16 z)
{
	if (allNode) 
	{
		delete[] allNode;
	}

	if (edgeLifeNode)
	{
		delete edgeLifeNode;
	}

	if (x >= 3 && y >= 3 && z >= 1)
	{
		liveTime = 0;
		sizeX = x;
		sizeY = y;
		sizeZ = z;
		allnum = x * y*z;
		numXY = x * y;

		if (z == 1)
		{
			allNode = new FOneNode2D[allnum];
			edgeLifeNode = new FOneNode2D();
		}
		else
		{
			allNode = new FOneNode3D[allnum];
			edgeLifeNode = new FOneNode3D();
		}

		uint32 index = 0;
		for (int iz = 0; iz < z; iz++)
		{
			for (int iy = 0; iy < y; iy++)
			{
				for (int ix = 0; ix < y; ix++)
				{
					InitOne(ix, iy, iz, index);
					index++;
				}
			}
		}
		return true;
	}
	return false;
}
void FLiftWorld::SetLiftStart(TArray<int> start)
{
	for (int i = 0; i < start.Num(); i++) 
	{
		SetNodeLift(start[i], 1);
	}
}


/**更新世界*/
void FLiftWorld::UpDataWorld()
{
	liveTime++;
	for (uint32 index = 0; index < allnum; index++)
	{
		allNode[index].UpDataLift();
	}

	for (uint32 index = 0; index < allnum; index++)
	{
		allNode[index].SaveBuffer();
	}
}
#pragma optimize("",on)